﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using Funq;
using ServiceStack;
using ServiceStack.Mvc;
using IAS.WebUI.ServiceInterface;
using ServiceStack.Auth;
using ServiceStack.Redis;
using ServiceStack.Data;
using ServiceStack.OrmLite;
using ServiceStack.OrmLite.SqlServer;
using System.IO;
using ServiceStack.Configuration;
using Mvc.ServiceInterface;
using ServiceStack.Caching;

namespace IAS.WEB
{
    public class AppHost : AppHostBase
    {
        public static AppConfig AppConfig;

        /// <summary>
        /// Default constructor.
        /// Base constructor requires a name and assembly to locate web service classes. 
        /// </summary>
        public AppHost()
            : base("IAS.WebUI", typeof(IASServices).Assembly)
        {

        }

        /// <summary>
        /// Application specific configuration
        /// This method should initialize any IoC resources utilized by your web service classes.
        /// </summary>
        /// <param name="container"></param>
        public override void Configure(Container container)
        {
            //Load environment config from text file if exists
            var liveSettings = "~/appsettings.txt".MapHostAbsolutePath();
            var appSettings = File.Exists(liveSettings)
                ? (IAppSettings)new TextFileSettings(liveSettings)
                : new AppSettings();
           
            AppConfig = new AppConfig(appSettings);
            container.Register(AppConfig);

            SetConfig(new HostConfig
            {
                DebugMode = appSettings.Get("DebugMode", true),
                StripApplicationVirtualPath = appSettings.Get("StripApplicationVirtualPath", false),
                AdminAuthSecret = appSettings.GetString("AuthSecret"),
                HandlerFactoryPath = "api"
            });

            

            //Config examples
            Plugins.Add(new PostmanFeature());
            Plugins.Add(new CorsFeature());

            //Enable Authentication an Registration
            Plugins.Add(new AuthFeature(() => new AuthUserSession(),
                new IAuthProvider[]
                {
                    //基于window域认证
                    //new AspNetWindowsAuthProvider(this) {  // Integrated Windows Auth
                    //    LoadUserAuthFilter = LoadUserAuthInfo,
                    //    AllowAllWindowsAuthUsers = true
                    //}, 
                    new CredentialsAuthProvider()        //HTML Form post of UserName/Password credentials  
                    { RedirectUrl = "~/NoPermission.html",SessionExpiry = TimeSpan.FromDays(7)}
                })
            {
                HtmlRedirect = "~/NoPermission.html",
                IncludeRegistrationService = true,
            });

            //Provide service for new users to register so they can login with supplied credentials.
            //Plugins.Add(new RegistrationFeature());
            //override the default registration validation with your own custom implementation
            //container.RegisterAs<CustomRegistrationValidator, IValidator<Register>>();

            //Redis
            container.Register<IRedisClientsManager>(c =>
                new PooledRedisClientManager("localhost:6379"));
            container.Register(c => c.Resolve<IRedisClientsManager>().GetCacheClient());

            //container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(
            //    AppSettings.GetString("AppDb"), PostgreSqlDialect.Provider));
            string connStr = System.Configuration.ConfigurationManager.ConnectionStrings["sqlserver"].ConnectionString;
            container.Register<IDbConnectionFactory>(new OrmLiteConnectionFactory(connStr, SqlServerDialect.Provider));
            var authRepo = new OrmLiteAuthRepository(container.Resolve<IDbConnectionFactory>())
                {
                    UseDistinctRoleTables = AppSettings.Get("UseDistinctRoleTables", true),                    
                };
            container.Register<IAuthRepository>(authRepo);
            
            //container.Register<ICacheClient>(new MemoryCacheClient());
            //var userRep = new InMemoryAuthRepository();
            container.Register<IUserAuthRepository>(authRepo);
            authRepo.InitSchema();
            //container.Resolve<IUserAuthRepository>().InitSchema();  
            Plugins.Add(new RequestLogsFeature());
            var authRepo1 = (OrmLiteAuthRepository)container.Resolve<IAuthRepository>();
           // ResetUsers(authRepo1);
            //Set MVC to use the same Funq IOC as ServiceStack
            ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
        }

        public static void ResetUsers(OrmLiteAuthRepository authRepo)
        {
            authRepo.DropAndReCreateTables();

            CreateUser(authRepo, 1, "admin", "admin", new List<string> { "admin","supperAdmin" }, new List<string> { "All" });
            CreateUser(authRepo, 2, "user", "user");
        }

        private static void CreateUser(OrmLiteAuthRepository authRepo,
          int id, string username, string password, List<string> roles = null, List<string> permissions = null)
        {
            string hash;
            string salt;
            new SaltedHash().GetHashAndSaltString(password, out hash, out salt);

            authRepo.CreateUserAuth(new UserAuth
            {
                Id = id,
                DisplayName = username + " DisplayName",
                Email = username + "@chinsan.com",
                UserName = username,
                FirstName = "First " + username,
                LastName = "Last " + username,
                PasswordHash = hash,
                Salt = salt,
                Roles = roles,
                Permissions = permissions
            }, password);

            authRepo.AssignRoles(id.ToString(), roles, permissions);
            
        }
      
    }
}